package goliath;

import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.converters.Converter;
import pulpfizz.pulp.body.*;
import pulpfizz.physics.BodyUtils;
import org.jbox2d.dynamics.Body;
import org.jbox2d.common.Vec2;
import pulpcore.sprite.Sprite;

import java.awt.*;
import java.awt.geom.Ellipse2D;

/**
 * Defines a class to save/load the state of the Physics engine into an XML string.
 *
 * This class currently just resets the world, and manually re-adds all the bodies
 * to the new scene.
 *
 *
 * @author will
 * @date Aug 9, 2008 5:51:25 PM
 */
public class PhysicsConverter implements Converter {

    public void marshal(Object o, HierarchicalStreamWriter writer, MarshallingContext context) {
        PhysicsLayer physics = (PhysicsLayer)o;

        writer.startNode("Bodies");
        for(int i=0;i< physics.size();i++) {
            Sprite sprite = physics.get(i);
            if(! (sprite instanceof Java2DBodySprite)) {
                continue;
            }
            Java2DBodySprite b = (Java2DBodySprite) sprite;

            writer.startNode("BodyDrawer");
            BodyDrawer bd = b.getBodyDrawer();
            if(bd instanceof ShapeBodyDrawer) {
                ShapeBodyDrawer sh = (ShapeBodyDrawer)bd;
                SimpleBodyDrawer sbd = new SimpleBodyDrawer(sh);
                bd = sbd;
            }

            context.convertAnother(bd);
            writer.endNode();

            writer.startNode("Body");
            Body s = ((BodySprite)physics.get(i)).getBody();
            context.convertAnother(s);
            writer.endNode();
        }
        writer.endNode();
    }

    public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
        PhysicsLayer physics = new PhysicsLayer(BasicDemo.getPhysics().getScaling());
        physics.fitToStage();
        physics.setGravity(new Vec2(0, -10.0f));

        while(reader.hasMoreChildren()) {
            reader.moveDown();
            if(reader.getNodeName().equals("Bodies")) {
                while(reader.hasMoreChildren()) {
                    reader.moveDown(); // "bodysprite"
                    BodyDrawer b = new SimpleBodyDrawer();
                    b = (BodyDrawer)context.convertAnother(b,SimpleBodyDrawer.class);
                    reader.moveUp();

                    reader.moveDown(); // "bodysprite"
                    Body body = new Body();
                    body = (Body)context.convertAnother(body,Body.class);
                    body.m_world = physics.getWorld();
                    Body body1 = BodyUtils.cloneBody(body);

                    Java2DBodySprite myp = new Java2DBodySprite(body1, physics, 3, b);
                    physics.add(myp);

                    reader.moveUp();

                }
            } else {
                System.out.println("error not bodies found");
            }
            reader.moveUp();
        }
        return physics;
    }

    public boolean canConvert(Class aClass) {
        return PhysicsLayer.class == aClass;
    }

}
